package deformation;

import deformation.line.*;
import deformation.point.*;
import handler.Handler;
import handler.LineHandler;
import handler.PointHandler;
import handler.UnsupportedHandlerException;

/**
 * a helper class to generate Affine, Similarity, Rigid Line and Point deformations
 *
 */
public class DeformationGenerator {

	private DeformationGenerator() {

	}

	public final static int AFFINE_POINT_DEFORMATION = 1001;
	public final static int SIMILARITY_POINT_DEFORMATION = 1002;
	public final static int RIGID_POINT_DEFORMATION = 1003;
	public final static int AFFINE_LINE_DEFORMATION = 2001;
	public final static int SIMILARITY_LINE_DEFORMATION = 2002;
	public final static int RIGID_LINE_DEFORMATION = 2003;

	public enum DeformationType {
		AffinePointDeformation, SimilarityPointDeformation, RigidPointDeformation, AffineLineDeformation, SimilarityLineDeformation, RigidLineDeformation;
		public Deformation generate(Handler handler) {
			return DeformationGenerator.generate(handler, this);
		}

		public Deformation generate(Handler handler, double alpha) {
			return DeformationGenerator.generate(handler, this, alpha);
		}

		public int getID() {
			return DeformationGenerator.getID(this);
		}
		
		public boolean isLine() {
			return DeformationGenerator.isLine(this);
		}
		
		public boolean isPoint() {
			return DeformationGenerator.isPoint(this);
		}
	}

	public static boolean isLine(DeformationType deformationType) {
		switch (deformationType) {
		case AffineLineDeformation:
			return true;
		case SimilarityLineDeformation:
			return true;
		case RigidLineDeformation:
			return true;
		default:
			return false;
		}
	}

	
	public static boolean isPoint(DeformationType deformationType) {
		switch (deformationType) {
		case AffinePointDeformation:
			return true;
		case SimilarityPointDeformation:
			return true;
		case RigidPointDeformation:
			return true;
		default:
			return false;
		}
	}
	
	public static DeformationType[] getAllDeformations() {
		return DeformationType.values();
	}

	public static int getID(DeformationType deformationType) {
		switch (deformationType) {
		case AffinePointDeformation:
			return AFFINE_POINT_DEFORMATION;
		case SimilarityPointDeformation:
			return SIMILARITY_POINT_DEFORMATION;
		case RigidPointDeformation:
			return RIGID_POINT_DEFORMATION;
		case AffineLineDeformation:
			return AFFINE_LINE_DEFORMATION;
		case SimilarityLineDeformation:
			return SIMILARITY_LINE_DEFORMATION;
		case RigidLineDeformation:
			return RIGID_LINE_DEFORMATION;
		default:
			return -1;
		}

	}

	public static Deformation generate(Handler handler,
			DeformationType deformationType) {
		switch (deformationType) {
		case AffinePointDeformation:
			if (handler instanceof PointHandler) {
				return new AffinePointDeformation((PointHandler) handler);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case SimilarityPointDeformation:
			if (handler instanceof PointHandler) {
				return new SimilarityPointDeformation((PointHandler) handler);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case RigidPointDeformation:
			if (handler instanceof PointHandler) {
				return new RigidPointDeformation((PointHandler) handler);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case AffineLineDeformation:
			if (handler instanceof LineHandler) {
				return new AffineLineDeformation((LineHandler) handler);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}
		case SimilarityLineDeformation:
			if (handler instanceof LineHandler) {
				return new SimilarityLineDeformation((LineHandler) handler);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}
		case RigidLineDeformation:
			if (handler instanceof LineHandler) {
				return new RigidLineDeformation((LineHandler) handler);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}

		default:
			System.err.println("unknown deformationType");
			return null;
		}

	}

	public static Deformation generate(Handler handler,
			DeformationType deformationType, double alpha) {
		switch (deformationType) {
		case AffinePointDeformation:
			if (handler instanceof PointHandler) {
				return new AffinePointDeformation((PointHandler) handler, alpha);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case SimilarityPointDeformation:
			if (handler instanceof PointHandler) {
				return new SimilarityPointDeformation((PointHandler) handler,
						alpha);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case RigidPointDeformation:
			if (handler instanceof PointHandler) {
				return new RigidPointDeformation((PointHandler) handler, alpha);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case AffineLineDeformation:
			if (handler instanceof LineHandler) {
				return new AffineLineDeformation((LineHandler) handler, alpha);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}
		case SimilarityLineDeformation:
			if (handler instanceof LineHandler) {
				return new SimilarityLineDeformation((LineHandler) handler,
						alpha);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}
		case RigidLineDeformation:
			if (handler instanceof LineHandler) {
				return new RigidLineDeformation((LineHandler) handler, alpha);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}

		default:
			System.err.println("unknown deformationType");
			return null;
		}

	}

	public static Deformation generate(Handler handler, int deformationID) {
		switch (deformationID) {
		case AFFINE_POINT_DEFORMATION:
			if (handler instanceof PointHandler) {
				return new AffinePointDeformation((PointHandler) handler);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case SIMILARITY_POINT_DEFORMATION:
			if (handler instanceof PointHandler) {
				return new SimilarityPointDeformation((PointHandler) handler);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case RIGID_POINT_DEFORMATION:
			if (handler instanceof PointHandler) {
				return new RigidPointDeformation((PointHandler) handler);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case AFFINE_LINE_DEFORMATION:
			if (handler instanceof LineHandler) {
				return new AffineLineDeformation((LineHandler) handler);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}
		case SIMILARITY_LINE_DEFORMATION:
			if (handler instanceof LineHandler) {
				return new SimilarityLineDeformation((LineHandler) handler);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}
		case RIGID_LINE_DEFORMATION:
			if (handler instanceof LineHandler) {
				return new RigidLineDeformation((LineHandler) handler);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}

		default:
			System.err.println("unknown deformationID");
			return null;
		}

	}

	public static Deformation generate(Handler handler, int deformationID,
			double alpha) {
		switch (deformationID) {
		case AFFINE_POINT_DEFORMATION:
			if (handler instanceof PointHandler) {
				return new AffinePointDeformation((PointHandler) handler, alpha);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case SIMILARITY_POINT_DEFORMATION:
			if (handler instanceof PointHandler) {
				return new SimilarityPointDeformation((PointHandler) handler,
						alpha);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case RIGID_POINT_DEFORMATION:
			if (handler instanceof PointHandler) {
				return new RigidPointDeformation((PointHandler) handler, alpha);
			} else {
				throw new UnsupportedHandlerException(PointHandler.class,
						handler.getClass());
			}
		case AFFINE_LINE_DEFORMATION:
			if (handler instanceof LineHandler) {
				return new AffineLineDeformation((LineHandler) handler, alpha);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}
		case SIMILARITY_LINE_DEFORMATION:
			if (handler instanceof LineHandler) {
				return new SimilarityLineDeformation((LineHandler) handler,
						alpha);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}
		case RIGID_LINE_DEFORMATION:
			if (handler instanceof LineHandler) {
				return new RigidLineDeformation((LineHandler) handler, alpha);
			} else {
				throw new UnsupportedHandlerException(LineHandler.class,
						handler.getClass());
			}

		default:
			System.err.println("unknown deformationID");
			return null;
		}

	}

}
